package org.blankie.util;

import java.util.concurrent.Executor;

import org.blankie.lang.Validate;

public class AsynchronousOrganizationManagerDelegate<O extends Organized,
                                                     N extends Organized,
                                                     L extends Organized> 
    implements AsynchronousOrganizationManager<O, N, L> {

    private final OrganizationManager<O, N, L> delegate;

    private Executor executor;
    
    /*
     * Get the value of executor
     *
     * @return the value of executor
     */
    public Executor getExecutor() {
        return executor;
    }

    /**
     * The <var>executor</var> property setter.
     */
    public void setExecutor(Executor executor) {
        this.executor = executor;
    }
    
    public AsynchronousOrganizationManagerDelegate(OrganizationManager<O, N, L> delegate) {
        Validate.parameterNotNull("delegate", delegate);
        this.delegate = delegate;
    }

    public void startGettingLeaves(final Organized managed, final Collector<L> into) {
        if (executor != null) {
            executor.execute(new Runnable() {
                public void run() {
                    try {
                        delegate.getLeaves(managed, new CollectionCollector<L>(into));
                    } catch (RuntimeException e) {
                        into.failed(e);
                    } finally {
                        into.close();
                    }
                }
            });
        }
    }

    public void startGettingNodes(final Organized managed, final Collector<N> into) {
        if (executor != null) {
            executor.execute(new Runnable() {
                public void run() {
                    try {
                        delegate.getNodes(managed, new CollectionCollector<N>(into));
                    } catch (RuntimeException e) {
                        into.failed(e);
                    } finally {
                        into.close();
                    }
                }
            });
        }
    }

    public void startGettingParent(final Organized managed, final Receiver<N> into) {
        if (executor != null) {
            executor.execute(new Runnable() {
                public void run() {
                    try {
                        into.set(delegate.getParent(managed));
                    } catch (RuntimeException e) {
                        into.failed(e);
                    }
                }
            });
        }
    }

    public void startGettingRoot(final Organized managed, final Receiver<N> into) {
        if (executor != null) {
            executor.execute(new Runnable() {
                public void run() {
                    try {
                        into.set(delegate.getRoot(managed));
                    } catch (RuntimeException e) {
                        into.failed(e);
                    }
                }
            });
        }
    }

    public void startGettingOrganization(final Organized managed, final Receiver<O> into) {
        if (executor != null) {
            executor.execute(new Runnable() {
                public void run() {
                    try {
                        into.set(delegate.getOrganization(managed));
                    } catch (RuntimeException e) {
                        into.failed(e);
                    }
                }
            });
        }
    }

    public boolean isLeaf(Organized object) {
        return delegate.isLeaf(object);
    }

    public boolean isNode(Organized object) {
        return delegate.isNode(object);
    }

    public boolean isRoot(Organized object) {
        return delegate.isRoot(object);
    }

    public boolean isOrganization(Organized object) {
        return delegate.isOrganization(object);
    }

}
